home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
libs
/
logwrite.1
/
logwrite
/
logwrites-1.1
/
intercepts.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-29
|
6KB
|
252 lines
/* intercepts.c: This file is currently the only source file for
the logwrites filter library.
Written by Adam J. Richter
Copyright 1996 Yggdrasil Computing, Inc.
Logwrites and its documentation, including this file, may be freely
copied under the terms and conditions of version 2 of the GNU General
Public License, as published by the Free Software Foundation
(Cambridge, Massachusetts, United States of America).
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <fcntl.h>
#include <stdarg.h>
#include <unistd.h>
#include <stdlib.h>
#include <syscall.h>
#include <stdio.h>
static int initialized = 0;
static int recursive = 0;
#define PREFIX "write "
static char cwd[MAXPATHLEN + 1] = PREFIX;
static char *install_log = NULL;
static char *do_backups = NULL;
static void
initialize (void) {
int len;
if (initialized) return;
if (getcwd(cwd,sizeof(cwd)) == NULL) {
strcpy (cwd, "?");
/* fail silently */
}
install_log = getenv ("INSTALL_LOG");
do_backups = getenv ("DO_BACKUPS");
initialized = 1;
}
static void
log_event( char *format, ... ) {
va_list arg_ptr;
FILE *log_file;
if (!initialized) initialize();
if (recursive || !install_log) return;
recursive = 1;
if ((log_file = fopen (install_log, "a")) == NULL) {
recursive = 0;
return;
}
va_start(arg_ptr,format);
vfprintf (log_file, format, arg_ptr);
va_end(arg_ptr);
fclose(log_file);
recursive = 0;
}
static int
gen_backup_filename (const char *filename, char *backup_filename /* OUT */) {
struct stat statbuf;
int i;
char *ptr;
sprintf (backup_filename, "%s.old", filename);
if (lstat (backup_filename, &statbuf) < 0) return;
ptr = backup_filename + strlen(backup_filename);
*(ptr++) = '.';
for (i = 1;i != 0;i++) {
sprintf (ptr, "%d", i);
if (lstat (backup_filename, &statbuf) < 0) return 1;
}
backup_filename[0] = '\0';
return 0;
}
static int
backup_file (const char *filename, char *backup_filename,
int regular_file_only) {
struct stat statbuf;
if (!initialized) initialize();
if (!do_backups) return 0;
if (recursive) return 0;
if (lstat (filename, &statbuf) >= 0 &&
(S_ISREG(statbuf.st_mode) || !regular_file_only) &&
gen_backup_filename(filename, backup_filename)) {
syscall(SYS_rename, filename, backup_filename);
return 1;
}
return 0;
}
int
link (const char *oldpath, const char *newpath) {
int result;
if ((result = syscall(SYS_link, oldpath, newpath)) >= 0) {
log_event("link %s %s %s\n", cwd, oldpath, newpath);
}
return result;
}
int
rename (const char *oldpath, const char *newpath) {
int result;
int backed_up;
char backup_filename[MAXPATHLEN+1];
backed_up = backup_file(newpath, backup_filename, 0);
if ((result = syscall(SYS_rename, oldpath, newpath)) >= 0) {
if (backed_up) {
log_event("backup %s %s %s\n", cwd, newpath, backup_filename);
}
log_event("rename %s %s %s\n", cwd, oldpath, newpath);
} else {
if (backed_up) {
syscall(SYS_rename, backup_filename, newpath);
}
}
return result;
}
int
symlink (const char *oldpath, const char *newpath) {
int result;
if ((result = syscall(SYS_symlink, oldpath, newpath)) >= 0) {
log_event("symlink %s %s %s\n", cwd, oldpath, newpath);
}
return result;
}
int
unlink (const char *filename) {
int result;
char backup_filename[MAXPATHLEN+1];
int backed_up;
backed_up = backup_file(filename, backup_filename, 0);
if ((result = syscall(SYS_unlink, filename)) >= 0) {
if (backed_up) {
log_event("backup %s %s %s\n", cwd, filename, backup_filename);
}
log_event("unlink %s %s\n", cwd, filename);
} else {
if (backed_up) {
syscall(SYS_rename, backup_filename, filename);
}
}
return result;
}
int
truncate (const char *filename, size_t length) {
int result;
char backup_filename[MAXPATHLEN+1];
int backed_up;
if (length == 0) {
backed_up = backup_file(filename, backup_filename, 0);
} else {
backed_up = 0;
}
if ((result = syscall(SYS_unlink, filename)) >= 0) {
if (backed_up) {
log_event("backup %s %s %s\n", cwd, filename, backup_filename);
}
if (length == 0) {
log_event("truncate %s %s %d\n", cwd, filename, length);
}
} else {
if (backed_up) {
syscall(SYS_rename, backup_filename, filename);
}
}
return result;
}
int
prev_mknod (const char *filename, mode_t mode, dev_t dev) {
int result;
if ((result = syscall(SYS_prev_mknod, mode, dev)) >= 0) {
log_event("mknod %s %s 0%o 0x%x\n", cwd, filename, mode, dev);
}
return result;
}
int
mkdir (const char *pathname, mode_t mode) {
int result;
if ((result = syscall(SYS_mkdir, pathname, mode)) >= 0) {
log_event("mkdir %s %s 0%o\n", cwd, pathname, mode);
}
return result;
}
/* XXX: Also intercept rmdir? */
int
open( const char *filename, int flags, ... ) {
int result;
mode_t mode;
va_list arg_ptr;
char backup_filename[MAXPATHLEN+1];
int backed_up;
int record_event;
va_start(arg_ptr,flags);
mode = va_arg(arg_ptr, mode_t);
va_end(arg_ptr);
/* Only log write-only opens that will create the file if it doesn't
exist. Otherwise, it is probably not an installation. */
if ((flags & O_ACCMODE) == O_WRONLY && (flags & O_CREAT) &&
(flags & O_TRUNC)) {
backed_up = backup_file(filename, backup_filename, 1);
record_event = 1;
} else {
backed_up = 0;
record_event = 0;
}
result = syscall(SYS_open, filename, flags, mode);
if (backed_up) {
if (result < 0) {
syscall(SYS_rename, backup_filename, filename);
} else {
log_event("backup %s %s %s\n", cwd, filename, backup_filename);
}
}
if (record_event) {
log_event("write %s %s 0x%x 0%o\n", cwd, filename, flags, mode);
}
return result;
}